#include "RtpPacket.hpp"
#include "common/HiCommonLog.hpp"
#include "common/hiScopeGuard.h"

namespace Hi {
// 如果Header的Padding被置位，则在packet末尾包含了一个额外的附加信息
bool RtpPacket::ParsePadding() {
	// Check padding field.
	if (this->header->padding == 0u) {
		return true;
	}
	// already parsed
	if(this->payloadPadding > 0) {
		return true;
	}

	// Must be at least a single payload byte.
	if (this->payloadLength == 0){
		HI_DEBUG("padding bit is set but no space for a padding byte, packet discarded");
		return false;
	}

	auto paddingLength = this->payload[this->payloadLength - 1];
	
	HiScopeGuard guard([&](){
		HI_DEBUG("header->padding:%d, payloadLength:%d, paddingLength:%d, -2:%x", 
			this->header->padding, payloadLength, 
			paddingLength, this->payload[this->payloadLength - 2]);
		
	});
	if (paddingLength == 0)	{
		HI_DEBUG("padding byte cannot be 0, packet discarded");
		return false;
	}

	if (this->payloadLength < size_t{paddingLength}) {
		HI_DEBUG("number of padding octets is greater than available space for payload, packet discarded");
		return false;
	}

	// update paddingLength
	this->payloadPadding = paddingLength;

	// update payloadLength
	this->payloadLength -= size_t{paddingLength};

	guard.dismissed();
	return true;
}

void RtpPacket::ParseExtensions() {	
	if (this->HasOneByteExtensions()) { // Parse One-Byte extension header.
		this->ParseExtensions_HasOneByteExtension();
	} else if (HasTwoBytesExtensions()) { // Parse Two-Bytes extension header.
		this->ParseExtensions_HasTwoByteExtensions();
	}
}

void RtpPacket::ParseExtensions_HasOneByteExtension() {	
    // Clear the One-Byte extension elements map.
    this->oneByteExtensions.clear();

	// 跳过4位，这4位为Extension的个数
    uint8_t *extensionStart = reinterpret_cast<uint8_t *>(this->extensionHeader) + 4;
    uint8_t *extensionEnd = extensionStart + GetExtensionHeaderLength();
    uint8_t *ptr = extensionStart;

    while (ptr < extensionEnd){
		uint8_t id = (*ptr & 0xF0) >> 4;
		size_t len = static_cast<size_t>(*ptr & 0x0F) + 1;

		if (ptr + 1 + len > extensionEnd){
			// MS_WARN_TAG(rtp, "not enough space for the announced One-Byte header extension element value");
			break;
		}

		// Store the One-Byte extension element in a map.
		this->oneByteExtensions[id] = reinterpret_cast<OneByteExtension *>(ptr);

		ptr += 1 + len;

		// Counting padding bytes.
		while ((ptr < extensionEnd) && (*ptr == 0)) {
			++ptr;
		}
    }
}

void RtpPacket::ParseExtensions_HasTwoByteExtensions() {
	// Clear the Two-Bytes extension elements map.
	this->twoBytesExtensions.clear();

	// 跳过4位，这4位为Extension的个数
	uint8_t *extensionStart = reinterpret_cast<uint8_t *>(this->extensionHeader) + 4;
	uint8_t *extensionEnd = extensionStart + this->GetExtensionHeaderLength();
	uint8_t *ptr = extensionStart;

	while (ptr < extensionEnd)
	{
		uint8_t id = *ptr;
		size_t len = *(++ptr);

		if (ptr + len > extensionEnd)
		{
			// MS_WARN_TAG(rtp, "not enough space for the announced Two-Bytes header extension element value");
			break;
		}

		// Store the Two-Bytes extension element in a map.
		this->twoBytesExtensions[id] = reinterpret_cast<TwoBytesExtension *>(ptr);

		ptr += len;

		// Counting padding bytes.
		while ((ptr < extensionEnd) && (*ptr == 0)) {
			++ptr;
		}
	}
}
} // namespace Hi End


